<?php

/* 
 * Manager/OperationManager.php
 */
namespace RHX\Model\Manager;

use Zend\Db\Adapter\Adapter;
use RHX\Model\Table\TransfertTable;
use RHX\Model\Object\Transfert;
use RHX\Model\Object\XCalculator;
use RHX\Model\Object\XData;
use RHX\Helper\RHDateTime;
use RHX\Model\Object\XRules;

class OperationManager{
    /**
     * Adapteur de base de données
     * @var Adapter
     */
    protected $adapter1;
    protected $adapter2;
    
    /**
     * Constructeur
     * 
     * @param \Zend\Db\Adapter\Adapter $adapter
     */
    public function __construct(Adapter $adapter1, Adapter $adapter2) {
	$this->adapter1 = $adapter1;
	$this->adapter2 = $adapter2;
    }
    
    /**
     * Adapteur de base de données
     * 
     * @return Adapter
     */
    public function getAdapter1(){
	return $this->adapter1;
    }
    
    /**
     * Adapteur de base de données
     * 
     * @return Adapter
     */
    public function getAdapter2(){
	return $this->adapter2;
    }
    
    /**
     * Productivité
     * 
     * @param int $siteId
     * @param string $date
     * @return real
     */
    public function getProductivite($siteId, $date){
	$nbTransaction = $this->getNbTransaction($siteId, $date);
	$heureTravaille = $this->getHeureTravaille($siteId, $date);
	$prod = $nbTransaction / $heureTravaille;
	return $prod;
    }
    
    /**
     * Transferts Entrant et/ou Sortant
     * 
     * @param int $siteId
     * @param string $date
     * @param int $type
     * @return real
     */
    public function getTransfert($siteId, $date, $type = Transfert::EntrantSortant){
	$tableTransfert = new TransfertTable($this->getAdapter1());
	$transferts = $tableTransfert->getTransfertOfOneDay($date, $type, $siteId);
	$value = 0.0;
	foreach ($transferts as $transfert){
	    $value += $this->getTransfertValue($transfert);
	}
	return $value;
    }
    
    /**
     * Nombre de transaction
     * 
     * @param int $site
     * @param string $date
     * @return int
     */
    public function getNbTransaction($site, $date) {
	$adapter	 = $this->getAdapter2();
	$sql		 = "SELECT COUNT(*) as nbTransaction FROM saleHead, store WHERE saleHead.idStore = store.idStore AND saleHead.canceled = 0 AND (saleHead.workerMeal = 0 OR saleHead.workerMeal is NULL) AND saleHead.orderDate = '$date' AND store.groupmentCode = $site";
	$result		 = $adapter->query($sql)
		->execute();
	$nbTransaction	 = 0;
	foreach ($result as $e) {
	    $nbTransaction = (int) $e['nbTransaction'];
	    break;
	}
	return $nbTransaction;
    }
    
    /**
     * Récupérer les heures travaillées
     * 
     * @param int $site
     * @param string $date
     * @param boolean $decimal
     * @return real|string
     */
    public function getHeureTravaille($site, $date, $decimal = true){
	$calculator = new XCalculator($this->getAdapter1());
	$travaille = new RHDateTime();
	$travaille->setTime();
	$plannings = $this->getPlanning($site, $date);
	foreach($plannings as $planning){
	    $data = $this->getData($planning, $date);
	    $ht = $calculator->calculHeureTravaillees($planning, $data, RHDateTime::dayName($date));
	    $travaille->addHours($ht->totalHours(), false);
	}
	return ($decimal) ? RHDateTime::toFloat($travaille->totalHours()) : $travaille->totalHours();
    }
    
    /**
     * Planning semaine ou la date est incluse
     * 
     * @param int $site
     * @param string $date
     * @return \RHX\Model\Object\PlanningSemaine
     */
    private function getPlanning($site, $date){
	$tablePlanning = new \RHX\Model\Table\PlanningSemaineTable($this->getAdapter1());
	return $plannings = $tablePlanning->getPlanningsByDate($date, $site);
    }
    
    /**
     * Donnée du jour
     * 
     * @param \RHX\Model\Object\PlanningSemaine $planning
     * @param string $date
     * @return XData
     */
    private function getData(\RHX\Model\Object\PlanningSemaine $planning, $date){
	$day = RHDateTime::dayName($date);
	$calculator= new XCalculator($this->getAdapter1());
	$data = $calculator->calculateOneDay($planning, $planning->getTemplate(), $day);
	return $data;
    }
    
    /**
     * Valeur d'une journée de transfert
     * 
     * @param \RHX\Model\Object\Transfert $transfert
     * @return float
     */
    private function getTransfertValue(Transfert $transfert){
	$calculator = new XCalculator($this->getAdapter1());
	$data = $calculator->oneDayCalcul($transfert->matricule, XRules::Present, $transfert->entree, $transfert->sortie, $transfert->pause, $transfert->repas, RHDateTime::dayName($transfert->journee));
	return $data->montant;
    }
    
    /**
     * Récupérer les informations de main d'oeuvre d'un site pour une date données<br>
     * La valeur de retour est un tableau avec les indices suivants : mo, heure, productivite, te, ts
     * 
     * @param int $site
     * @param string $date
     * @return array
     */
    public function getMO($site, $date){
	$data = array(
	    'mo' => 0.0,
	    'heure' => 0.0,
	    'productivite' => 0.0,
	    'te' => 0.0,
	    'ts' => 0.0,
	);
	$employes = $this->getEmployeBySite($site);
	$plannings = $this->getPlannings($employes, $date);
        //echo '<pre>' .count($plannings) .'</pre>';
	$day = RHDateTime::dayName($date);
	$calculator = new XCalculator($this->getAdapter1());
	foreach($plannings as $p){
	    $dataDay = $calculator->calculateOneDay($p, null, $day);
	    $data['heure'] += $this->getHeureTotal($p, $dataDay, $day, $calculator);
	    $data['mo'] += $this->getMOTotal($p, $dataDay, $day, $calculator);
	    $data['te'] += $this->getTransfertValueOfOneDay($site, $date, Transfert::Entrant);
	    $data['ts'] += $this->getTransfertValueOfOneDay($site, $date, Transfert::Sortant);
	    $data['productivite'] += $this->getProductiviteValue($site, $date, $data['heure']);
	}
	return $data;
    }
    
    /**
     * Récupération de la productivité
     * 
     * @param int $site
     * @param string $date
     * @param real $heure
     */
    public function getProductiviteValue($site, $date, $heure, $round = 2){
	$nbTransactions = $this->getNbTransaction_($site, $date);
	if($heure == 0){
	    return 0.0;
	}
	return round($nbTransactions / $heure, $round);
    }
    
    /**
     * Récupération des MO de la journée sur un site
     * 
     * @param \RHX\Model\Object\PlanningSemaine $planning
     * @param XData $data
     * @param string $day
     * @param XCalculator $calculator
     * @return real
     */
    public function getHeureTotal($planning, $data, $day, $calculator = null){
	$calculator = is_null($calculator) ? new XCalculator($this->getAdapter1()) : $calculator;
	$heure = $calculator->calculHeureTotales($planning, $data, $day);
        //echo '<pre>' .RHDateTime::toFloat($heure->totalHours()) .'</pre>';
	return RHDateTime::toFloat($heure->totalHours());
    }
    
    /**
     * Récupération des MO totale travaillées
     * 
     * @param \RHX\Model\Object\PlanningSemaine $planning
     * @param XData $data
     * @param string $day
     * @param XCalculator $calculator
     * @return real
     */
    public function getMOTotal($planning, $data, $day, $calculator = null){
	$calculator = is_null($calculator) ? new XCalculator($this->getAdapter1()) : $calculator;
	$mo = $calculator->calculMOTotal($planning, $data, $day);
	return $mo;
    }
    
    /**
     * Récupération des valeurs des transferts entrant ou sortant
     * 
     * @param int $site
     * @param string $date
     * @param int $type
     * @return real
     */
    public function getTransfertValueOfOneDay($site, $date, $type = Transfert::Entrant){
	$tableTransfert = new TransfertTable($this->getAdapter1());
	$transferts = $tableTransfert->getTransfertOfOneDay($date, $site, $type);
	$value = 0.0;
	$pauseTime = '00:30';
	foreach($transferts as $t){
	    $diff = RHDateTime::diffHours($t->sortie, $t->entree);
	    if ((int) $t->pause == 1) {
		$diff = RHDateTime::diffHours($diff, $pauseTime);
	    }
	    $employe = $t->getEmploye();
	    $dataCP = $employe->getDataCP($date);
	    $value += $dataCP['taux'] * $dataCP['coef'] * RHDateTime::toFloat($diff);
	}
	return $value;
    }
    
    /**
     * Liste des employés d'un site
     * 
     * @param int $site
     * @return array
     */
    public function getEmployeBySite($site){
	$tableEmploye = new \RHX\Model\Table\EmployeTable($this->getAdapter1());
	$employes = $tableEmploye->getEmployesBySiteEx2($site);
	return $this->transformToArray($employes);
    }
    
    public function getPlannings($employes, $date){
	$in = $this->transformToInParameter($employes);
	$sql = "SELECT * FROM rh_planning_semaine WHERE '$date' BETWEEN lundi AND dimanche AND matricule IN ($in)";
	$result = $this->getAdapter1()
		->query($sql)->execute();
	$array = array();
	foreach ($result as $r){
	    $p = new \RHX\Model\Object\PlanningSemaine($this->getAdapter1(), $r);
	    $array[] = $p;
	}
	return $array;
    }
    
    /**
     * Nombre de transaction pour une date données
     * 
     * @param int $site
     * @param string $date
     * @return int
     */
    public function getNbTransaction_($site, $date) {
	$adapter	 = $this->getAdapter2();
	$sql		 = "SELECT COUNT(*) as nbTransaction FROM saleHead, store WHERE saleHead.idStore = store.idStore AND saleHead.canceled = 0 AND (saleHead.workerMeal = 0 OR saleHead.workerMeal is NULL) AND saleHead.orderDate = '$date' AND store.groupmentCode = $site";
	$result		 = $adapter->query($sql)
		->execute();
	$nbTransaction	 = 0;
	foreach ($result as $e) {
	    $nbTransaction = (int) $e['nbTransaction'];
	    break;
	}
	return $nbTransaction;
    }
    
    /**
     * Transformer un ResultSet en Array
     * 
     * @param ResultSet $resultSet
     * @return array
     */
    private function transformToArray($resultSet){
	$array = array();
	foreach($resultSet as $r){
	    $array[] = $r;
	}
	return $array;
    }
    
    /**
     * Retourne un tableau ne contenant que les matricules des employés
     * 
     * @param ResultSet $employes
     * @return array
     */
    private function transformToMatriculeArray($employes){
	$array = array();
	foreach($employes as $e){
	    $array[] = $e->matricule;
	}
	return $array;
    }
    
    /**
     * Transforme un tableau de matricule en chaine de caractère
     * 
     * @param array $employes
     * @return string
     */
    private function transformToInParameter($employes){
	$matricules = $this->transformToMatriculeArray($employes);
        $matricules[] = 0;
	return implode(',', $matricules);
    }
}
